package com.yoo.ons.function.login

import android.app.Activity
import android.content.Context
import android.content.Intent
import android.view.View
import android.view.inputmethod.InputMethodManager
import androidx.core.view.isVisible
import androidx.core.widget.addTextChangedListener
import com.google.firebase.FirebaseException
import com.google.firebase.FirebaseTooManyRequestsException
import com.google.firebase.auth.FirebaseAuthInvalidCredentialsException
import com.google.firebase.auth.FirebaseUser
import com.google.firebase.auth.PhoneAuthCredential
import com.google.firebase.auth.PhoneAuthOptions
import com.google.firebase.auth.PhoneAuthProvider
import com.google.firebase.auth.PhoneAuthProvider.OnVerificationStateChangedCallbacks
import com.google.firebase.auth.ktx.auth
import com.google.firebase.ktx.Firebase
import com.yoo.chat.kit.utils.StatusBarUtil
import com.yoo.module_base.utils.SaveDeviceUtil
import com.yoo.module_base.utils.setOnClickCallback
import com.yoo.module_base.view.codeview.VerificationCodeView
import com.yoo.ons.ToastUtil.showToast
import com.yoo.ons.base.BaseVMActivity
import com.yoo.ons.base.HttpRequestListener
import com.yoo.ons.databinding.ActivityPhoneLoginBinding
import com.yoo.ons.function.MainActivity
import com.yoo.ons.function.register.RegisterActivity
import com.yoo.ons.model.LoginResultModel
import java.util.concurrent.TimeUnit

class PhoneLoginActivity : BaseVMActivity<ActivityPhoneLoginBinding, PhoneViewModel>(
    ActivityPhoneLoginBinding::inflate,
    PhoneViewModel::class.java
) {
    private var auth = Firebase.auth
    private var mCredential: PhoneAuthCredential? = null
    private var storedVerificationId: String = ""
    private var resendToken: PhoneAuthProvider.ForceResendingToken? = null
    private var smsCodeShow: Boolean = false
    private lateinit var callbacks: OnVerificationStateChangedCallbacks
    val requestCode = 1001
    val resultCode = 1002

    override fun initView() {
        super.initView()
        binding.titleBar.setBackListener {
            if (smsCodeShow) {
                binding.editCode.clearInputContent()
                binding.phoneOutsideContainer.visibility = View.VISIBLE
                binding.codeOutsideContainer.visibility = View.GONE
                binding.actSendCode.isSend = false
                smsCodeShow = false
            } else {
                finish()
            }
        }
        binding.titleBar.setTitleBarPadding(StatusBarUtil.getStatusBarHeight(this))
    }

    override fun initData() {

    }

    override fun initListener() {
        super.initListener()
        callbacks = object : OnVerificationStateChangedCallbacks() {
            override fun onVerificationCompleted(credential: PhoneAuthCredential) {
                hideProgressDialog()
                val inputStr = credential.smsCode
                val strArray: Array<String> =
                    (inputStr?.split("".toRegex())?.dropLastWhile { it.isEmpty() }
                        ?.toTypedArray()
                        ?: arrayOf())

                for (i in strArray.indices) {
                    binding.editCode.setText(strArray[i])
                }
                mCredential = credential
            }

            override fun onVerificationFailed(p0: FirebaseException) {
                hideProgressDialog()
                when (p0) {
                    is FirebaseAuthInvalidCredentialsException -> {
                        // Invalid request
                        showToast("Code send failed. Please try again.")
                    }

                    is FirebaseTooManyRequestsException -> {
                        // The SMS quota for the project has been exceeded
                        showToast("Failed to send the verification code. Please use another login method")
                    }

                }
            }

            override fun onCodeSent(
                verificationId: String,
                token: PhoneAuthProvider.ForceResendingToken,
            ) {
                hideProgressDialog()
                storedVerificationId = verificationId
                resendToken = token
                binding.actSendCode.startTime()
                if (binding.phoneOutsideContainer.isVisible) {
                    binding.phoneOutsideContainer.visibility = View.GONE
                    binding.codeOutsideContainer.visibility = View.VISIBLE
                    binding.txtPhoneNumber.text = "+1${binding.editPhone.text}"
                    smsCodeShow = true
                }

            }

        }

        binding.editPhone.requestFocus()
        // 延迟显示软键盘
        binding.editPhone.postDelayed({
            // 显示软键盘
            val imm = getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
            imm.showSoftInput(binding.editPhone, InputMethodManager.SHOW_IMPLICIT)
        }, 100)

        binding.editPhone.addTextChangedListener {
            binding.phoneNext.isEnabled = binding.editPhone.text.toString().length == 10
        }
        binding.editCode.setInputCompleteListener(object :
            VerificationCodeView.InputCompleteListener {
            override fun inputComplete() {
                binding.codeNext.isEnabled = binding.editCode.inputContent.isNotEmpty()
            }

            override fun deleteContent() {
                binding.codeNext.isEnabled = binding.editCode.inputContent.isNotEmpty()
            }

        })

        binding.phoneNext.setOnClickCallback {
            showProgressDialog(this)
            val options = PhoneAuthOptions.newBuilder(auth)
                .setPhoneNumber("+1" + binding.editPhone.text.toString()) // Phone number to verify
                .setTimeout(60L, TimeUnit.SECONDS) // Timeout and unit
                .setActivity(this) // Activity (for callback binding)
                .setCallbacks(callbacks)
                .build()
            PhoneAuthProvider.verifyPhoneNumber(options)
        }

        binding.codeNext.setOnClickCallback {
            if (mCredential != null) {
                signInWithPhoneAuthCredential(mCredential!!)
            } else {
                if (storedVerificationId != "") {
                    val credential = PhoneAuthProvider.getCredential(
                        storedVerificationId,
                        binding.editCode.inputContent
                    )
                    signInWithPhoneAuthCredential(credential)
                }
            }
        }

        binding.actSendCode.setOnClickCallback {
            resendVerificationCode(binding.editPhone.text.toString(), resendToken)
        }

    }

    private fun signInWithPhoneAuthCredential(credential: PhoneAuthCredential) {
        auth.signInWithCredential(credential)
            .addOnCompleteListener(this) { task ->
                if (task.isSuccessful) {
                    // Sign in success, update UI with the signed-in user's information
                    val user = task.result?.user
                    // 隐藏软键盘
                    val imm = getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
                    imm.hideSoftInputFromWindow(binding.editPhone.windowToken, 0)

                    phoneLogin(user)
                } else {
                    if (task.exception is FirebaseAuthInvalidCredentialsException) {
                        if ((task.exception as FirebaseAuthInvalidCredentialsException).errorCode == "ERROR_INVALID_VERIFICATION_CODE") {
                            showToast("code error")
                        } else {
                            showToast(task.exception?.message.toString())
                        }
                    }
                }
            }
    }

    private fun phoneLogin(user: FirebaseUser?) {
        if (intent.getStringExtra("source") == null) {
            mViewModel?.getLogin(object : HttpRequestListener<LoginResultModel>() {
                override fun addRequestParams(params: HashMap<String, Any>) {
                    params["accountType"] = 1
                    params["account"] = user?.uid ?: ""
                    params["mobile"] = binding.txtPhoneNumber.text.toString()
                }

                override fun success(t: LoginResultModel?) {
                    t?.apply {
                        SaveDeviceUtil.saveToken(t.token)
                        SaveDeviceUtil.saveUserCode(t.userCode)
                        SaveDeviceUtil.saveUserValid(t.isUserValid)
                        SaveDeviceUtil.saveAvatarUrl(t.avatarUrl)
                        SaveDeviceUtil.saveDeleteAccount(false)
                        if (t.isUserValid) {
                            MainActivity.start(this@PhoneLoginActivity)
                        } else {
                            RegisterActivity.start(this@PhoneLoginActivity)
                        }
                        finish()
                    }
                }

            })
        } else {
            mViewModel?.getAccountBind(object : HttpRequestListener<LoginResultModel>() {
                override fun addRequestParams(params: HashMap<String, Any>) {
                    params["accountType"] = 1
                    params["account"] = user?.uid ?: ""
                    params["mobile"] = binding.txtPhoneNumber.text.toString()
                }

                override fun success(t: LoginResultModel?) {
                    t?.apply {
                        val intent = Intent()
                        intent.putExtra("mobile", binding.txtPhoneNumber.text.toString())
                        setResult(resultCode, intent)
                        finish()
                    }
                }

                override fun error(throwable: Throwable) {
                    super.error(throwable)
                    showToast(throwable.message)
                }

            })
        }
    }


    private fun resendVerificationCode(
        phoneNumber: String,
        token: PhoneAuthProvider.ForceResendingToken?,
    ) {
        val optionsBuilder = PhoneAuthOptions.newBuilder(auth)
            .setPhoneNumber("+1$phoneNumber") // Phone number to verify
            .setTimeout(60L, TimeUnit.SECONDS) // Timeout and unit
            .setActivity(this) // (optional) Activity for callback binding
            .setCallbacks(callbacks) // OnVerificationStateChangedCallbacks
        if (token != null) {
            optionsBuilder.setForceResendingToken(token) // callback's ForceResendingToken
        }
        PhoneAuthProvider.verifyPhoneNumber(optionsBuilder.build())
    }


    companion object {
        fun start(context: Context, source: String? = null) {
            val intent = Intent(context, PhoneLoginActivity::class.java)
            intent.putExtra("source", source)
            context.startActivity(intent)
        }

        fun startForResult(activity: Activity, source: String? = null) {
            val intent = Intent(activity, PhoneLoginActivity::class.java)
            intent.putExtra("source", source)
            activity.startActivityForResult(intent, 1001)
        }
    }
}